package com.xyzwps.paimon.furina.common

import org.springframework.http.HttpStatus
import org.springframework.web.servlet.function.ServerRequest
import org.springframework.web.servlet.function.ServerResponse

class AppException(val code: AppErrorCode, message: String = code.message, val payload: Any? = null) :
    Exception(message)

/**
 * Business logic error
 */
internal val BIZ_ERROR = HttpStatus.NOT_IMPLEMENTED

/**
 * Interface layer error
 */
internal val BAD_REQUEST = HttpStatus.BAD_REQUEST

/**
 * Unauthenticated
 */
internal val UNAUTHENTICATED = HttpStatus.UNAUTHORIZED

/**
 * Unexpected error
 */
internal val SERVER_ERROR = HttpStatus.INTERNAL_SERVER_ERROR

/**
 * Unauthorized
 */
internal val UNAUTHORIZED = HttpStatus.FORBIDDEN


enum class AppErrorCode(val status: HttpStatus, val message: String) {
    YOU_HAVE_BEEN_AUTHENTICATED(UNAUTHORIZED, "你已登录"),
    NOT_AUTHENTICATED(UNAUTHENTICATED, "尚未登录"),
    ACCOUNT_LOCKED(UNAUTHENTICATED, "账户被锁定"),
    ACCOUNT_DISABLED(UNAUTHENTICATED, "账户被禁用"),

    REQUEST_PARSING_FAILED(BAD_REQUEST, "请求解析错误"),
    REQUEST_VALIDATION_FAILED(BAD_REQUEST, "请求检查失败"),
    PATH_VAR_INVALID(BAD_REQUEST, "Path variable is invalid."),
    REQUEST_ARG_FORMAT_INVALID(BAD_REQUEST, "请求参数不正确"),
    SEARCH_PARAM_INVALID(BAD_REQUEST, "Search parameter is invalid."),
    SEARCH_PARAM_REQUIRED(BAD_REQUEST, "Search parameter is required."),

    LOGIN_INFO_INVALID(BAD_REQUEST, "登录信息不正确"),
    USER_HAS_NO_PASSWORD(BIZ_ERROR, "用户未设置密码"),
    VCODE_CANNOT_BE_USED(BIZ_ERROR, "验证码无效"),
    VCODE_NOT_MATCH(BIZ_ERROR, "验证码不正确"),
    VCODE_NOT_SEND_OR_TIMEOUT(BIZ_ERROR, "验证码尚未发送或已过期"),
    VCODE_SEND_ALREADY(BIZ_ERROR, "验证码已发送"),
    VCODE_SEND_TOO_MANY(BIZ_ERROR, "你已发送太多次验证码"),
    VCODE_FORMAT_INVALID(BAD_REQUEST, "验证码格式不正确"),
    PHONE_HAS_BEEN_USED(BIZ_ERROR, "手机号已被使用"),
    PHONE_FORMAT_INVALID(BAD_REQUEST, "手机号格式不正确"),

    PAGE_SIZE_INVALID(BAD_REQUEST, "页号不正确"),

    POST_COLLECTION_NOT_FOUND(BAD_REQUEST, "文章分组不存在"),
    POST_NOT_FOUND(BAD_REQUEST, "文章不存在"),

    NICKNAME_FORMAT_INVALID(BAD_REQUEST, "昵称格式不正确"),
    AVATAR_URL_FORMAT_INVALID(BAD_REQUEST, "头像链接格式不正确"),
    USER_DESCRIPTION_FORMAT_INVALID(BAD_REQUEST, "用户描述格式不正确"),

    TOKEN_INVALID(UNAUTHENTICATED, "Token 不正确"),

    UNHANDLED(SERVER_ERROR, "未处理错误"),
}

fun wrapError(e: Throwable, req: ServerRequest): ServerResponse {
    return when (e) {
        is AppException -> {
            log.warn("request {} {} error", req.method(), req.path(), e)
            ServerResponse.status(e.code.status)
                .body(mapOf("msg" to e.message, "payload" to e.payload, "code" to e.code.name))
        }

        else -> {
            log.error("request {} {} unhandled error", req.method(), req.path(), e)
            val code = AppErrorCode.UNHANDLED
            ServerResponse.status(500)
                .body(mapOf("msg" to code.message, "code" to code))
        }
    }
}